package com.dusk.util
{
    
    import avmplus.getQualifiedClassName;
    
    import base.BaseAnimation;
    
    import base.BaseObject;
    
    import com.game.view.IAnimation;
    import com.game.view.display.AnimationClip;
    import com.game.view.display.BitmapMovieClip;
    import com.game.view.display.McMovieClip;
    
    import com.game.view.display.Texture;
    
    import com.game.view.display.TextureGroup;
    
    import com.greensock.TweenMax;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.DisplayObject;
    import flash.display.DisplayObjectContainer;
    import flash.display.MovieClip;
    import flash.display.Sprite;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.system.System;
    import flash.utils.Dictionary;
    import flash.utils.clearInterval;
    import flash.utils.setInterval;
    
    public class McUtil extends UtilBase
    {
        public function McUtil()
        {
            super();
        }
        
        /**
         * 翻转对象
         * @param displayObject 目标显示对象
         * @param scale 缩放倍率
         *
         */
        public static function flipHorizontal(displayObject:DisplayObject, scale:int):void
        {
            var matrix:Matrix = displayObject.transform.matrix;
            var matA:int = matrix.a;
            matrix.a = scale == 1 ? Math.abs(matA) : -Math.abs(matA);
            displayObject.transform.matrix = matrix;
        }
        
        
        /**
         * 停止mc内所有子mc
         * @param mc 目标mc
         */
        public static function stopAllChildren(mc:MovieClip):void
        {
            for (var i:int = 0; i < mc.numChildren; i++)
            {
                var obj:DisplayObject = mc.getChildAt(i);
                if (obj && obj is MovieClip)
                {
                    (obj as MovieClip).stop();
                    stopAllChildren(obj as MovieClip);
                }
            }
        }
        
        /**
         * 播放mc内所有子mc
         * @param mc 目标mc
         */
        public static function startAllChildren(mc:MovieClip):void
        {
            for (var i:int = 0; i < mc.numChildren; i++)
            {
                var obj:DisplayObject = mc.getChildAt(i);
                if (obj && obj is MovieClip)
                {
                    (obj as MovieClip).play();
                    startAllChildren(obj as MovieClip);
                }
            }
        }
        
        /**
         * 播放mc内所有子mc一帧
         * @param mc 目标mc
         */
        public static function nextFrameAllChildren(mc:MovieClip):void
        {
            for (var i:int = 0; i < mc.numChildren; i++)
            {
                var obj:DisplayObject = mc.getChildAt(i);
                if (obj && obj is MovieClip)
                {
                    if ((obj as MovieClip).currentFrame >= (obj as MovieClip).totalFrames)
                    {
                        (obj as MovieClip).gotoAndStop(1);
                        return;
                    }
                    else
                    {
                        (obj as MovieClip).gotoAndStop((obj as MovieClip).currentFrame + 1);
                    }
                    nextFrameAllChildren(obj as MovieClip);
                }
            }
        }
        
        /**
         * 让传入DisplayObject产生BitMap影子
         * @param displayObj 目标displayObject
         *
         */
        public static function shallowEffect(displayObj:DisplayObject):void
        {
            var bd:BitmapData = new BitmapData(displayObj.width, displayObj.height, true, 0xFFFFFF);
            bd.draw(displayObj, new Matrix(displayObj.transform.matrix.a, 0, 0, 1, displayObj.width / 2, displayObj.height));
            var bm:Bitmap = new Bitmap(bd);
            bm.x = displayObj.x - displayObj.width / 2;
            bm.y = displayObj.y - displayObj.height;
            if (displayObj is BaseObject)
            {
                if (BaseObject(displayObj).isStatic())
                {
                    bm.x += (Math.random() - 0.5) * 5;
                }
            }
            if (displayObj.parent)
            {
                var idx:int = displayObj.parent.getChildIndex(displayObj);
                displayObj.parent.addChildAt(bm, idx);
                TweenMax.to(bm, 1, {
                    "alpha": 0, "onCompleteParams": [bm], "onComplete": function (param1:Bitmap):*
                    {
                        if (param1 && param1.parent && param1.parent.contains(param1))
                        {
                            param1.bitmapData.dispose();
                            param1.bitmapData = null;
                            param1.parent.removeChild(param1);
                        }
                    }
                });
            }
            else
            {
                bm.bitmapData.dispose();
                bm.bitmapData = null;
            }
        }
        
        /**
         * 重绘显示对象内的文字对象，请在super()实例化父类后调用
         *
         */
        public static function redrawTxt(container:DisplayObjectContainer):void
        {
            TextUtil.redrawTxt(container);
        }
        
        /**
         * 将元件的注册原点调整至元件中心，前提是原始注册点在左上角
         * @param sprite
         */
        public static function letRegisterPointToCenter(sprite:Sprite):void
        {
            if (!sprite)
            {
                throw new Error("displayObject must be none null");
            }
            var widthOff:Number = sprite.width / 2;
            var heightOff:Number = sprite.height / 2;
            for (var idx:int = 0; idx < sprite.numChildren; idx++)
            {
                with (sprite.getChildAt(idx) as DisplayObject)
                {
                    x -= widthOff;
                    y -= heightOff;
                }
            }
        }
        
        /**
         * 碰撞测试
         * @param obj1 对象1
         * @param obj2 对象2
         * @param container 父对象容器
         * @return 是否相交
         */
        public static function testIntersects(obj1:DisplayObject, obj2:DisplayObject, container:DisplayObjectContainer):Boolean
        {
            return obj1.getBounds(container).intersects(obj2.getBounds(container));
        }
        
        /**
         * 循环测试每层的显示对象是否加载完毕，加载完毕后执行目标函数
         * @param container 检测到目标对象
         * @param func 目标执行函数
         *
         */
        public static function checkLoadOK(container:DisplayObjectContainer, func:Function):void
        {
            var si:int = int(setInterval(function ():*
            {
                var isOk:Boolean = true;
                for (var i:int = 0; i < container.numChildren; i++)
                {
                    if (!container.getChildAt(i))
                    {
                        isOk = false;
                        break;
                    }
                }
                if (isOk)
                {
                    clearInterval(si);
                    if (func)
                    {
                        func.call();
                    }
                }
            }, 100));
        }
        
        /**
         * 获取两个对象之间的角度
         * @param obj1 对象1
         * @param obj2 对象2
         * @return 角度
         */
        public static function getTwoObjectAngle(obj1:*, obj2:*):Point
        {
            if (!obj1 || !obj2)
            {
                return new Point(0, 0);
            }
            return MathUtil.getAngleByTwoPoint(new Point(obj1.x, obj1.y), new Point(obj2.x, obj2.y));
        }
        
        /**
         * 获取显示对象上指定类所处的父级对象
         * @param object 目标显示对象
         * @param cls 目标类
         * @return 父级对象中满足条件的对象
         */
        public static function getClassInParents(object:DisplayObject, cls:Class):*
        {
            while (object.parent)
            {
                object = object.parent;
                if (object is cls)
                {
                    return object;
                }
            }
            return null;
        }
        
        /**
         * 判断显示对象是否有指定类
         * @param object 目标显示对象
         * @param cls 目标类
         * @return 是否有指定类
         */
        public static function hasClassInParents(object:DisplayObject, cls:Class):Boolean
        {
            while (object.parent)
            {
                object = object.parent;
                if (object is cls)
                {
                    return true;
                }
            }
            return false;
        }
        
        /**
         * 清除显示对象内的所有子对象
         * @param container 目标显示对象
         */
        public static function removeAllChildren(container:DisplayObjectContainer):void
        {
            while (container.numChildren > 0)
            {
                var obj:DisplayObject = container.getChildAt(0);
                if (obj is Bitmap)
                {
                    (obj as Bitmap).bitmapData.dispose();
                    (obj as Bitmap).bitmapData = null;
                }
                container.removeChild(obj);
            }
        }
        
        /**
         * 获取到距离mainObj最近的对象
         * @param mainObj 主Object
         * @param objArr Object集合
         * @return 距离最近的Object
         * @param getType 定义距离类型（x；y；dis）
         *
         */
        public static function getNearestObj(mainObj:BaseObject, objArr:Array, getType:String = "dist"):BaseObject
        {
            var _loc1_:Array = [];
            var _loc2_:DisplayObject;
            switch (getType)
            {
                case "x":
                case "X":
                    for each(_loc2_ in objArr)
                    {
                        _loc1_.push(Math.abs(_loc2_.x - mainObj.x))
                    }
                    return objArr[_loc1_.sort(Array.RETURNINDEXEDARRAY).indexOf(0)];
                case "y":
                case "Y":
                    for each(_loc2_ in objArr)
                    {
                        _loc1_.push(Math.abs(_loc2_.x - mainObj.x))
                    }
                    return objArr[_loc1_.sort(Array.RETURNINDEXEDARRAY).indexOf(0)];
                default:
                    for each(_loc2_ in objArr)
                    {
                        _loc1_.push(AUtils.GetDisBetweenTwoObj(_loc2_, mainObj))
                    }
                    return objArr[_loc1_.sort(Array.RETURNINDEXEDARRAY).indexOf(0)];
            }
        }
        
        /**
         * 将一个一维的动画绘制为一个AnimationClip
         * @param mc
         * @param info
         * @param animateType
         * @param smoothing
         * @return
         */
        public static function analyseMovieClipToAnimateClip(mc:MovieClip, info:Object = null, animateType:int = 0, smoothing:Boolean = false):AnimationClip
        {
            var prvSpace:Sprite = new Sprite();
            prvSpace.addChild(mc);
            switch (animateType)
            {
                case 0:
                    var group:TextureGroup = new TextureGroup();
                    var totalFrame:int = mc.totalFrames;
                    for (var i:int = 1; i <= totalFrame; i++)
                    {
                        mc.gotoAndStop(i);
                        nextFrameAllChildren(mc);
                        var rect:Rectangle = mc.getBounds(prvSpace);
                        if (rect.isEmpty()) rect = new Rectangle(0, 0, 1, 1);
                        var tex:Texture = new Texture();
                        tex.content = new BitmapData(rect.width, rect.height, true, 0xFFFFFF);
                        tex.content.draw(prvSpace, new Matrix(1, 0, 0, 1, -rect.x, -rect.y), null, null, null, smoothing);
                        
                        var opaque:Rectangle = BitmapUtil.getOpaqueRegion(tex.content);
                        rect.offset(opaque.x, opaque.y);
                        tex.content = BitmapUtil.cropTransparentRegion(tex.content);
                        
                        tex.region = rect;
                        group.addTexture(tex);
                    }
                    group.clearSameKeyFrame();
                    return new BitmapMovieClip(group);
                case 1:
                    return new McMovieClip(mc);
                default:
                    throw new Error("animateType参数错误");
            }
        }
        
        /**
         * 将mc转换为动画字典
         * --转换时间太长，已弃用
         * @param mc 目标mc
         * @param info 哪些类需要转换为特定的帧
         * @param animateType IAnimate种类，0为位图，1为矢量图
         * @param smoothing 是否平滑
         * @return 动画字典
         * @example analyseMovieClipToAnimateDict(mc,{
         * fashion_yf:1,
         * fashion_wq:1,
         * fashion_cb:1
         },0,true);
         */
        public static function analyseMovieClipToAnimateDict(mc:MovieClip, info:Object = null, animateType:int = 0, smoothing:Boolean = false):Dictionary
        {
            var targetClass:Array = UtilBase.getAllKeys(info);
            var totalFrame:uint = mc.totalFrames;
            var animateDict:Dictionary = new Dictionary();
            var singleAnimation:IAnimation;
            for (var i:uint = 1; i <= totalFrame; i++)
            {
                mc.gotoAndStop(i);
                if (mc.numChildren == 0) throw new Error("mcContainer is Empty");
                var actMc:MovieClip = mc.getChildAt(0) as MovieClip;
                if (!actMc) throw new Error("mc.getChildAt(0) is not MovieClip");
                var totalFrame2:uint = actMc.totalFrames;
                var group:TextureGroup = new TextureGroup();
                for (var j:uint = 1; j <= totalFrame2; j++)
                {
                    actMc.gotoAndStop(j);
                    nextFrameAllChildren(actMc);
                    //把所有的部位都进行换皮
                    for (var k:int = 0; k < actMc.numChildren; k++)
                    {
                        var child:MovieClip = actMc.getChildAt(k) as MovieClip;
                        if (!child) continue;
                        var childClassName:String = getQualifiedClassName(child);
                        for each (var target:String in targetClass)
                        {
                            if (childClassName.indexOf(target) != -1)
                            {
                                child.gotoAndStop(info[target]);
                                break;
                            }
                        }
                    }
                    //生成私有空间用于绘制bitmapData
                    var prvSpace:Sprite = new Sprite();
                    prvSpace.addChild(actMc);
                    var rect:Rectangle = actMc.getBounds(prvSpace);
                    if (rect.isEmpty()) rect = new Rectangle(0, 0, 1, 1);
                    switch (animateType)
                    {
                        case 0:
                            var tex:Texture = new Texture();
                            tex.content = new BitmapData(rect.width, rect.height, true, 0xFFFFFF);
                            tex.content.draw(prvSpace, new Matrix(1, 0, 0, 1, -rect.x, -rect.y), null, null, null, smoothing);
                            
                            var opaque:Rectangle = BitmapUtil.getOpaqueRegion(tex.content);
                            rect.offset(opaque.x, opaque.y);
                            tex.content = BitmapUtil.cropTransparentRegion(tex.content);
                            
                            tex.region = rect;
                            group.addTexture(tex);
                            break;
                        case 1:
//							var actMcClone:MovieClip = new MovieClip();
//							actMcClone.graphics.copyFrom(actMc.graphics);
//							actMcClone.x = actMcClone.y = 0;
//							container.addChild(actMcClone as MovieClip);
                            break;
                        default:
                            throw new Error("animateType参数错误");
                    }
                }
                if (mc.currentFrameLabel == null) throw new Error("当前帧没有帧标签");
                switch (animateType)
                {
                    case 0:
                        group.clearSameKeyFrame();
                        singleAnimation = new BitmapMovieClip(group);
                        animateDict[mc.currentFrameLabel] = singleAnimation;
//						animateDict[mc.currentLabel] = singleAnimation;
//						使用currentFrameLabel保持紧凑性，不会出现没有帧标签的情况
                        break;
                    case 1:
                        actMc.parent.removeChild(actMc);
                        singleAnimation = new McMovieClip(actMc);
                        animateDict[mc.currentFrameLabel] = singleAnimation;
                        break;
                    default:
                        throw new Error("animateType参数错误");
                }
            }
            System.gc();
            return animateDict;
        }
        
        /**
         * 此API由BaseAnimation在获取新的动作时调用
         * 获取指定动作的AnimationClip
         */
        public static function analyseMovieClipByAction(mc:MovieClip, info:Object = null, action:String = "", animateType:int = 0, smoothing:Boolean = false):IAnimation
        {
            var targetClass:Array = UtilBase.getAllKeys(info);
            var singleAnimation:IAnimation;
            
            try
            {
                mc.gotoAndStop(action);
            } catch (e:Error)
            {
                //找不到动作
                return null;
            }
            
            
            if (mc.numChildren == 0) throw new Error("mcContainer is Empty");
            var actMc:MovieClip = mc.getChildAt(0) as MovieClip;
            if (!actMc) throw new Error("mc.getChildAt(0) is not MovieClip");
            var totalFrame2:uint = actMc.totalFrames;
            var group:TextureGroup = new TextureGroup();
            for (var j:uint = 1; j <= totalFrame2; j++)
            {
                actMc.gotoAndStop(j);
                nextFrameAllChildren(actMc);
                //把所有的部位都进行换皮
                for (var k:int = 0; k < actMc.numChildren; k++)
                {
                    var child:MovieClip = actMc.getChildAt(k) as MovieClip;
                    if (!child) continue;
                    var childClassName:String = getQualifiedClassName(child);
                    for each (var target:String in targetClass)
                    {
                        if (childClassName.indexOf(target) != -1)
                        {
                            child.gotoAndStop(info[target]);
                            break;
                        }
                    }
                }
                //生成私有空间用于绘制bitmapData
                var prvSpace:Sprite = new Sprite();
                prvSpace.addChild(actMc);
                var rect:Rectangle = actMc.getBounds(prvSpace);
                if (rect.isEmpty()) rect = new Rectangle(0, 0, 1, 1);
                switch (animateType)
                {
                    case 0:
                        var tex:Texture = new Texture();
                        tex.content = new BitmapData(rect.width, rect.height, true, 0xFFFFFF);
                        tex.content.draw(prvSpace, new Matrix(1, 0, 0, 1, -rect.x, -rect.y), null, null, null, smoothing);
                        
                        var opaque:Rectangle = BitmapUtil.getOpaqueRegion(tex.content);
                        rect.offset(opaque.x, opaque.y);
                        tex.content = BitmapUtil.cropTransparentRegion(tex.content);
                        
                        tex.region = rect;
                        group.addTexture(tex);
                        break;
                    case 1:
//							var actMcClone:MovieClip = new MovieClip();
//							actMcClone.graphics.copyFrom(actMc.graphics);
//							actMcClone.x = actMcClone.y = 0;
//							container.addChild(actMcClone as MovieClip);
                        break;
                    default:
                        throw new Error("animateType参数错误");
                }
            }
            if (mc.currentFrameLabel == null) throw new Error("当前帧没有帧标签");
            switch (animateType)
            {
                case 0:
                    group.clearSameKeyFrame();
                    singleAnimation = new BitmapMovieClip(group);
                    return singleAnimation;
                case 1:
                    actMc.parent.removeChild(actMc);
                    singleAnimation = new McMovieClip(actMc);
                    return singleAnimation;
                default:
                    throw new Error("animateType参数错误");
            }
        }
    }
}










